package com.t2t.top;

import java.nio.ByteBuffer;

/**
 * Created by yangpengfei on 2016/9/7.
 * <p/>
 * NIO的Buffer提供一个可以直接访问系统物理内存的类——DirectBuffer。
 * DirectBuffer类继承自ByteBuffer，但和普通的ByteBuffer不同。普通的ByteBuffer仍在JVM堆上分配内存，其最大内存受到最大堆内存的限制。
 * 而DirectBuffer直接分配在物理内存中，并不占用堆空间。
 * 在访问普通的ByteBuffer时，系统总是会使用一个“内核缓冲区”进行操作。
 * 而DirectBuffer所处的位置，就相当于这个“内核缓冲区”。
 * 因此使用DirectBuffer是一种更加接近内存底层的方法，所以它的速度比普通的ByteBuffer更快。
 */
public class BufferTest {
    public static void main(String[] args) {
        //两段测试代码分别使用了DirectBuffer和堆上的ByteBuffer，并进行了大量的读写访问。测试结果是DirectBuffer相对耗时20ms,而ByteBuffer相应耗时33ms.虽然都很快，但从比例上来说，DirectBuffer接近快了一倍。如果把外层的循环次数由10万改为100万，DirectBuffer use : 105ms，而ByteBuffer use : 225ms，快了一倍多。
        testByteBuffer();
        testDirectBuffer();

        //虽然有访问速度上的优势，但是在创建和销毁DirectBuffer的花费却远比ByteBuffer高。
        testCreateByteBuffer();
        testCreateDirectBuffer();
    }

    public static void testByteBuffer() {
        long start = System.currentTimeMillis();
        ByteBuffer buffer = ByteBuffer.allocate(500);//分配500个字节的ByteBuffer
        for (int i = 0; i < 100000; i++) {
            for (int j = 0; j < 99; j++) {
                buffer.putInt(j);            //向DirectBuffer写入数据
            }
            buffer.flip();
            for (int j = 0; j < 99; j++) {
                buffer.get();                    //从DirectBuffer中读取数据
            }
            buffer.clear();
        }
        System.out.println("ByteBuffer use : " + (System.currentTimeMillis() - start) + "ms");
    }

    public static void testDirectBuffer() {
        long start = System.currentTimeMillis();
        ByteBuffer buffer = ByteBuffer.allocateDirect(500);//分配500个字节的DirectBuffer
        for (int i = 0; i < 100000; i++) {
            for (int j = 0; j < 99; j++) {
                buffer.putInt(j);            //向DirectBuffer写入数据
            }
            buffer.flip();
            for (int j = 0; j < 99; j++) {
                buffer.get();                    //从DirectBuffer中读取数据
            }
            buffer.clear();
        }
        System.out.println("DirectBuffer use : " + (System.currentTimeMillis() - start) + "ms");
    }

    public static void testCreateByteBuffer() {
        long start = System.currentTimeMillis();
        for (int i = 0; i < 20000; i++) {
            ByteBuffer b = ByteBuffer.allocate(1000);
        }
        System.out.println("create ByteBuffer use : " + (System.currentTimeMillis() - start) + "ms");
    }

    public static void testCreateDirectBuffer() {
        long start = System.currentTimeMillis();
        for (int i = 0; i < 20000; i++) {
            ByteBuffer b = ByteBuffer.allocateDirect(1000);
        }
        System.out.println("create DirectBuffer use : " + (System.currentTimeMillis() - start) + "ms");
    }
}
